// multer.cpp : main project file.

#include "stdio.h"
#include "unistd.h"
#include "stdlib.h"

typedef long long data_t;

void
matrix_print(data_t *matr, size_t n_col, const char *title);

data_t *matr0, *matr1;
size_t n_col;
int verbose = 0;

void
usage(const char *me)
{
  fprintf(stderr, "Usage: %s [-h][-v] n-rows\n", me);
  exit(EXIT_FAILURE);
}

void
matrix_generate(data_t *matr, size_t n_col)
{
  size_t nn = n_col * n_col;
  size_t i;
  for(i = 0 ; i < nn ; ++i)
    *matr++ = (data_t)i;
}

void
matrix_zero(data_t *matr, size_t n_col)
{
  size_t nn = n_col * n_col;
  size_t i;
  for(i = 0 ; i < nn ; ++i)
    *matr++ = (data_t)0;
}

void
matrix_print(data_t *matr, size_t n_col, const char *title)
{
  fprintf(stderr, "----------------\n");
  size_t i, j;
  for(i = 0 ; i < n_col ; ++i){
    for(j = 0 ; j < n_col ; ++j)
      fprintf(stderr, "%qd ",  (long long)*matr++);
    fprintf(stderr, "\n");
  }
}

int 
main(int argc, char **argv)
{
  int c;
  const char *me = argv[0];

  while((c = getopt(argc, argv, "hv")) != -1) switch(c){
  case 'v':
    verbose = 1;
    break;
  case 'h':
  case '?':
  default:
    usage(me);
  }
  argc -= optind;
  argv += optind;
  
  if(argc != 1)
    usage(me);
	
  n_col = atoi(argv[0]);

  fprintf(stderr, "n_col == %u\n", n_col);

  matr0 = malloc(sizeof(data_t) * n_col * n_col);
  matr1 = malloc(sizeof(data_t) * n_col * n_col);

  matrix_generate(matr0, n_col);
  if(verbose)
    matrix_print(matr0, n_col, "Matrix");
//	matrix_zero(matr1, n_col);

  data_t *rp = matr1;
  data_t *col_p, *col_p_end = matr0 + n_col, 
    *row_p, *row_p_end = matr0 + n_col * n_col;

  for(row_p = matr0 ; row_p != row_p_end ; row_p += n_col){
    data_t *inn_p1_end = row_p + n_col;
    for(col_p = matr0 ; col_p != col_p_end ; col_p += 1){
      data_t *inn_p1 = row_p, *inn_p2 = col_p; 
      data_t s = 0;
      while(inn_p1 != inn_p1_end){
	s += *inn_p1++ * *inn_p2;
	inn_p2 += n_col;
      }
      *rp++ = s;
    }
  }
  if(verbose)
    matrix_print(matr1, n_col, "Result");
  fprintf(stderr, "CHK: matr[%u,%u] = %qd\n", 
	  n_col -1, n_col -1, (long long) matr1[n_col*n_col - 1]);

  return 0;
}
